package com.up.selfshop.controller;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.unionpay.acp.sdk.AcpService;
import com.unionpay.acp.sdk.LogUtil;
import com.unionpay.acp.sdk.SDKConfig;
import com.up.selfshop.entity.UserEntity;
import com.up.selfshop.mapper.UserEntityMapper;
import com.up.selfshop.res.Res;
import com.up.selfshop.res.ResLogin;
import com.up.selfshop.res.ResTransCode;
import com.up.selfshop.util.StrUtil;

@Controller
@RequestMapping("/user")
public class UserController extends BaseController {
	static String TRANS_CODE = "reuw46r8atgsf6g1w5erwer";

	@Autowired
	private UserEntityMapper userEntityMapper;

	// 测试用
	@RequestMapping("/")
	public String index() {
		return "user-api.html";
	}

	// 登陆：
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	@ResponseBody
	public Res login( //
			@RequestParam String uname, //
			@RequestParam String passwd, //
			@RequestParam String nonce, //
			@RequestParam String sign) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("uname", uname);
		UserEntity userEntity = userEntityMapper.findByUname(map);
		if (userEntity == null) {
			return Res.err("用户不存在");
		} else if (!userEntity.getPasswd().equals(passwd)) {
			return Res.err("用户名或密码错误");
		} else {
			String newToken = UUID.randomUUID().toString().replaceAll("-", "");
			userEntity.setToken(newToken);
			userEntityMapper.updateByPrimaryKey(userEntity);
			ResLogin res = new ResLogin();
			res.setToken(newToken);
			return res.signed();
		}
	}

	// 用户交易授权码：
	@RequestMapping(value = "/trans_code", method = RequestMethod.POST)
	@ResponseBody
	public Res transCaptcha( //
			@RequestParam String token, //
			@RequestParam String nonce, //
			@RequestParam String sign) {
		ResTransCode res = new ResTransCode();
		res.setTransCode(TRANS_CODE);
		return res.signed();
	}

	// 用户授权：
	@RequestMapping(value = "/grant", method = RequestMethod.POST)
	public String grant( //
			@RequestParam String token, //
			@RequestParam String mer_id, //
			@RequestParam String box_id, //
			Model model) {
		model.addAttribute("mer_id", mer_id);
		model.addAttribute("box_id", box_id);
		if ("user is granted".equals("用户已授权")) {
			return "grant_return.html";
		} else {
			String grant_result = jlwt_bg("merId", "txnTime", "orderId", "accNo", "customerNm", "certifTp", "certifId", "phoneNo", "cvn2", "expired");
			model.addAttribute("grant_result", grant_result);
			return "grant_return.html";
		}
	}

	// 用户请求开门：
	@RequestMapping(value = "/open_door", method = RequestMethod.POST)
	public String open_door( //
			@RequestParam String token, //
			@RequestParam String mer_id, //
			@RequestParam String box_id, //
			Model model) {
		// 创建订单，向商户发起开门请求
		String orderId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		model.addAttribute("order_id", orderId);
		model.addAttribute("mer_id", mer_id);
		model.addAttribute("box_id", box_id);
		return "open_door_return.html";
	}

	// 轮询订单状态：
	@RequestMapping(value = "/order_stat", method = RequestMethod.POST)
	@ResponseBody
	public Res order_stat( //
			@RequestParam String token, //
			@RequestParam String order_id) {
		return new Res().signed();
	}

	// 订单结果：
	@RequestMapping("/order_result")
	public String order_result( //
			String order_id, //
			String mer_id, //
			String box_id, //
			Model model) {
		model.addAttribute("order_id", order_id);
		model.addAttribute("mer_id", mer_id);
		model.addAttribute("box_id", box_id);
		return "order_result.html";
	}

	// 后台建立委托
	@RequestMapping("/jlwt_bg")
	@ResponseBody
	public String jlwt_bg(//
			@RequestParam String merId, //
			@RequestParam String txnTime, //
			@RequestParam String orderId, //
			@RequestParam String accNo, //
			@RequestParam String customerNm, //
			@RequestParam String certifTp, //
			@RequestParam String certifId, //
			@RequestParam String phoneNo, //
			@RequestParam String cvn2, //
			@RequestParam String expired) {
		merId = "777290058152112"; // 商户号： 777290058152112
		txnTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); // 订单发送时间：20171213154141
		orderId = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); // 商户订单号：20171213154141216
		accNo = "6216261000000000018"; // 卡号： 6216261000000000018
		customerNm = "全渠道"; // 姓名： 全渠道
		certifTp = "01"; // 证件类型： 01
		certifId = "341126197709218366"; // 证件号码： 341126197709218366
		phoneNo = "13552535506"; // 手机号： 13552535506
		cvn2 = ""; // cvn2： cvn2-仅贷记卡
		expired = ""; // 有效期： 有效期-仅贷记卡

		Map<String, String> contentData = new HashMap<String, String>();

		/*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
		contentData.put("version", SDKConfig.getConfig().getVersion()); // 版本号
		contentData.put("encoding", "UTF-8"); // 字符集编码
												// 可以使用UTF-8,GBK两种方式
		contentData.put("signMethod", SDKConfig.getConfig().getSignMethod()); // 签名方法
																				// 目前只支持01-RSA方式证书加密
		contentData.put("txnType", "72"); // 交易类型
		contentData.put("txnSubType", "11"); // 交易子类型
		contentData.put("bizType", "000501"); // 业务类型
		contentData.put("channelType", "07"); // 渠道类型

		/*** 商户接入参数 ***/
		contentData.put("merId", merId); // 商户号码（商户号码777290058152112仅做为测试调通交易使用，该商户号配置了需要对敏感信息加密）测试时请改成自己申请的商户号，【自己注册的测试777开头的商户号不支持代收产品】
		contentData.put("accessType", "0"); // 接入类型，商户接入固定填0，不需修改
		contentData.put("orderId", orderId); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
		contentData.put("txnTime", txnTime); // 订单发送时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
		contentData.put("accType", "01"); // 账号类型

		// 姓名，证件类型+证件号码至少二选一必送，手机号可选，贷记卡的cvn2,expired可选。
		Map<String, String> customerInfoMap = new HashMap<String, String>();
		customerInfoMap.put("certifTp", certifTp); // 证件类型
		customerInfoMap.put("certifId", certifId); // 证件号码
		customerInfoMap.put("customerNm", customerNm); // 姓名

		customerInfoMap.put("phoneNo", phoneNo); // 手机号
		// 当卡号为贷记卡的时候cvn2,expired可选上送
		customerInfoMap.put("cvn2", cvn2); // 卡背面的cvn2三位数字
		customerInfoMap.put("expired", expired); // 有效期 年在前月在后

		// 如果商户号开通了【商户对敏感信息加密】的权限那么需要对
		// accNo，pin和phoneNo，cvn2，expired加密（如果这些上送的话），对敏感信息加密使用：
		String accNoEnc = AcpService.encryptData(accNo, "UTF-8"); // 这里测试的时候使用的是测试卡号，正式环境请使用真实卡号
		contentData.put("accNo", accNoEnc);
		contentData.put("encryptCertId", AcpService.getEncryptCertId()); // 加密证书的certId，配置在acp_sdk.properties文件
																			// acpsdk.encryptCert.path属性下
		String customerInfoStr = AcpService.getCustomerInfoWithEncrypt(customerInfoMap, null, "UTF-8");

		// 如果商户号未开通【商户对敏感信息加密】权限那么不需对敏感信息加密使用：
		// contentData.put("accNo", "6216261000000000018");
		// //这里测试的时候使用的是测试卡号，正式环境请使用真实卡号
		// String customerInfoStr =
		// DemoBase.getCustomerInfo(customerInfoMap,null);

		contentData.put("customerInfo", customerInfoStr);

		/** 对请求参数进行签名并发送http post请求，接收同步应答报文 **/
		Map<String, String> reqData = AcpService.sign(contentData, "UTF-8"); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
		String requestBackUrl = SDKConfig.getConfig().getBackRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
																			// acpsdk.backTransUrl
		Map<String, String> rspData = AcpService.post(reqData, requestBackUrl, "UTF-8"); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

		/** 对应答码的处理，请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考-------------> **/
		// 应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
		if (!rspData.isEmpty()) {
			if (AcpService.validate(rspData, "UTF-8")) {
				LogUtil.writeLog("验证签名成功");
				String respCode = rspData.get("respCode");
				if (("00").equals(respCode)) {
					// 成功
				} else {
					// 其他应答码为失败请排查原因或做失败处理
				}
			} else {
				LogUtil.writeErrorLog("验证签名失败");
				// 检查验证签名失败的原因
			}
		} else {
			// 未返回正确的http状态
			LogUtil.writeErrorLog("未获取到返回报文或返回http状态码非200");
		}
		String reqMessage = StrUtil.genHtmlResult(reqData);
		String rspMessage = StrUtil.genHtmlResult(rspData);
		return "请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage;
	}
}
